# -*- coding: utf-8 -*-
import datetime
import hashlib
import threading
import time
import os
# httpx==0.27.0
import httpx
import atexit
import configparser

from httpx import ReadError, ReadTimeout
# watchdog==4.0.0
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import tkinter
from tkinter import messagebox

ini_path = "./settings.ini"

send_url = None

# 形变文件
defo_file = None
# 散射文件
scat_file = None


def read_ini():
    config = configparser.ConfigParser()
    config.read(ini_path, encoding='utf8')
    return config


def write_log(string):
    with open("log.log", "a", encoding="UTF-8") as f:
        now = time.localtime()
        formatted_time = time.strftime("%Y-%m-%d %H:%M:%S", now)
        f.write(f"[{formatted_time}]" + string + "\n")


def query_file(folder_path):
    """查询当前最新的bin文件"""
    defo_time = 0
    scat_time = 0
    global defo_file
    global scat_file
    # 获取所有文件
    for dirpath, dirnames, filenames in os.walk(folder_path):
        # 路径，该路径下的所有文件夹，该路径下的所有文件
        # https://www.jb51.net/python/2966784ma.htm
        for filename in filenames:
            if "defo" in filename:  # 形变文件
                # 获取文件的创建时间
                ctime = os.path.getctime(os.path.join(dirpath, filename))
                if ctime > defo_time:
                    defo_time = ctime
                    defo_file = os.path.join(dirpath, filename)

            if "scat" in filename:  # 散射文件
                # 获取文件的创建时间
                ctime = os.path.getctime(os.path.join(dirpath, filename))
                if ctime > scat_time:
                    scat_time = ctime
                    scat_file = os.path.join(dirpath, filename)


def log_request(request):
    """请求前回调"""
    write_log(f"发送前 hook: {request.method} {request.url} - Waiting for response")


def log_response(response):
    """请求后回调"""
    request = response.request
    write_log(f"发送后 hook: {request.method} {request.url} - Status {response.status_code}")


client = httpx.Client(event_hooks={'request': [log_request], 'response': [log_response]})  # 绑定钩子函数


def send(url, files, request_header, num):
    try:
        r = httpx.post(url, files=files, headers=request_header)
        write_log(r.text)
    except Exception as e:
        # '远程主机强迫关闭了一个现有的连接。'
        # 还有捕获其他异常情况
        if num < 10:
            num += 1
            write_log(f"发送失败，失败原因{e}")
            write_log(f"第{num}次重发")
            time.sleep(3)
            send(url, files, request_header, num)


def send_file(test_radar_no, test_mission_id, new_file_name, bin_path, num):
    """发送文件"""
    try:
        # 计算TOKEN
        mas_token = "1f8e1a2f-5e5f-453c-a05b-014075dd6f"
        text = mas_token + test_radar_no
        md5 = hashlib.md5()
        md5.update(text.encode('utf-8'))
        satoken = md5.hexdigest().upper()

        files = {
            "equipmentid": (None, test_radar_no),
            "missionid": (None, test_mission_id),
            "file": (new_file_name, open(bin_path, "rb"), "application/octet-stream")
        }

        request_header = {
            "Satoken": satoken,
        }

        send(send_url, files, request_header, num)
    except PermissionError as e:
        # open 时报Permission
        if num < 10:
            num += 1
            write_log(f"发送失败，失败原因{e}")
            write_log(f"第{num}次重发")
            time.sleep(3)
            send_file(test_radar_no, test_mission_id, new_file_name, bin_path, num)


def pre_send_file(bin_path):
    """判断是否是需要的文件"""
    # 读取配置文件
    config = read_ini()
    production_radar_no = config["RADAR"]["PRODUCTION_RADAR_NO"]
    test_radar_no = config["RADAR"]["TEST_RADAR_NO"]
    production_mission_id = config["RADAR"]["PRODUCTION_MISSION_ID"]
    test_mission_id = config["RADAR"]["TEST_MISSION_ID"]
    server_path = config["SERVER"]["SERVER_PATH"]

    # write_log(f"新增的文件的路径:{bin_path}")
    # 读取文件信息
    file_name = os.path.basename(bin_path)
    # write_log(f"新增的文件名:{file_name}")
    # 35aw6fuMSBmQt_vBYa2w91A_defo_1020049_1706776648_14056_1710118869.bin

    # 判断是形变文件还是散射文件
    global send_url
    if "defo" in file_name:  # 形变文件
        split_str = "defo_"
        send_url = server_path + "/API/mas/radarcalculate/v3/point-cloud-data/upload"
    elif "scat" in file_name:  # 散射文件
        split_str = "scat_"
        send_url = server_path + "/API/mas/radarcalculate/v3/scatter-intensity-data/upload"
    else:
        return False

    file_name_after = file_name.split(split_str)[1]
    file_name_split_list = file_name_after.split("_")

    if production_radar_no == file_name_split_list[0] and production_mission_id == file_name_split_list[1]:

        # 制作新的批次文件名
        file_name_split_list[0] = test_radar_no
        file_name_split_list[1] = test_mission_id
        # 更改时间戳
        file_name_split_list[3] = str(int(time.time())) + ".bin"

        new_file_name_after = "_".join(file_name_split_list)
        new_file_name = file_name.split(split_str)[0] + split_str + new_file_name_after
        write_log(f"发送的文件名:{new_file_name}")
        try:
            write_log(f"开始发送=============================")
            num = 0
            send_file(test_radar_no, test_mission_id, new_file_name, bin_path, num)
            write_log(f"发送结束=============================")
            write_log(f"==============================================================================")
        except Exception as e:
            # ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))
            # [Errno 13] Permission denied: 'D:\\test\\24-5\\17\\L92o3N4BRVK72Ih2dusYYw_defo_1020049_1706776648_14060_1710119820.bin'
            write_log(f"发送失败：报错信息{e}")
            write_log(f"发送失败：报错类型{type(e)}")
    else:
        # write_log(f"不是匹配文件:radar_no:{file_name_split_list[0]},mission_id:{file_name_split_list[1]}")
        pass


def continuous_push():
    """持续推送"""
    config = read_ini()
    # 间隔推送时间
    interval_time = eval(config["MODE"]["INTERVAL_TIME"])
    if defo_file is not None:
        while True:
            threading.Thread(target=pre_send_file, args=(defo_file,)).start()
            time.sleep(interval_time)

    elif scat_file is not None:
        while True:
            threading.Thread(target=pre_send_file, args=(scat_file,)).start()
            time.sleep(interval_time)
    else:
        time.sleep(60)
        continuous_push()


class MyHandler(FileSystemEventHandler):
    def on_created(self, event):
        if not event.is_directory:
            bin_path = event.src_path
            if "defo" in bin_path:
                global defo_file
                defo_file = bin_path
                pre_send_file(bin_path)
            if "scat" in bin_path:
                global scat_file
                scat_file = bin_path
                pre_send_file(bin_path)


def listening_folders(file_path):
    """监听文件夹变化,开启监听一个文件"""
    observer = Observer()
    event_handler = MyHandler()
    observer.schedule(event_handler, path=file_path, recursive=True)
    observer.start()


@atexit.register
def program_exit():
    """程序退出(手动，自动，崩溃)时执行"""
    write_log("程序退出")


def run():
    # 1.读取配置文件
    config = read_ini()
    radar_folder = config["FOLDER"]["RADAR_FOLDER"]
    # radar_date = config["FOLDER"]["RADAR_DATE"]

    # 判断是否是持续发送
    if bool(eval(config["MODE"]["IS_CONTINUOUS_PUSH"])):
        # 调用方法查询最新的bin文件
        query_file(radar_folder)
        # 调用持续发送的方法
        threading.Thread(target=continuous_push).start()

    # 2.开启监听文件夹内的文件变化
    listening_folders(radar_folder)

    # 3.判断运行时长，持续运行
    days = config["RUNTIME"]["DAYS"]
    # 终点时间
    end_time = datetime.datetime.now() + datetime.timedelta(days=eval(days))
    write_log(f"开始运行：运行至时间：{end_time}")

    tk = tkinter.Tk()
    tk.withdraw()
    messagebox.showinfo(title="提示", message="已打开！")

    is_running = True
    while is_running:
        if datetime.datetime.now() < end_time:
            time.sleep(60 * 1)
        else:
            is_running = False


if __name__ == '__main__':
    # 打包命令，最好单独搞个虚拟环境打包
    # pyinstaller -F -w --i .\favicon.ico .\test.py
    run()
